package org.dynamo.database.reverse.config.internal;
/*******************************************************************************
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Jean Neveux - initial API and implementation
 *******************************************************************************/

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.dynamo.database.reverse.config.internal.log.Log;
import org.dynamo.database.reverse.emf.configuration.configuration.Profiles;
import org.dynamo.database.reverse.emf.configuration.configuration.TypeURI;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.Type;

/**
 * Manage the UML Profiles
 */
public class UMLProfiles {
	private Map<String, Profile> _profile;
	private Map<String, Map<String, Type>> types;
	private Model model;
	private UMLResources umlResources;
	
	private static final Log log = Log.getLog(UMLProfiles.class);
	
	
	public void setModel(Model model)
	{
		this.model = model;
	}
	
	public UMLProfiles() {
		init();
	}

	public UMLProfiles(Model model) {
		setModel(model);
		init();
	}
	
	private void init()
	{
		_profile = new HashMap<String, Profile>(2);
		types =  new HashMap<String, Map<String,Type>>(2);
		umlResources = new UMLResources();
	}

	
	public void addProfile(Profiles profile)
	{
		if(!_profile.containsKey(profile.getName()) && profile.isActive())
		{
			URI modelURI = null;
			if(profile.getTypeURI() == TypeURI.PATHMAP)
			{
				if(!umlResources.getUriMap().containsKey(URI.createURI(profile.getSource())))
				{
					umlResources.getUriMap().put(URI.createURI(profile.getSource()),
							URI.createURI(profile.getTarget()));
				}
				modelURI = URI.createURI(profile.getSource()+profile.getModel());
			} else if(profile.getTypeURI() == TypeURI.PLATFORM) {
				modelURI = URI.createURI(profile.getTarget()+profile.getModel(), true);
			} else {
				modelURI = URI.createURI(profile.getTarget(), true);
			}
			Profile pr = (Profile) umlResources.contentload(modelURI);
			this.model.applyProfile(pr);
			_profile.put(profile.getName(),pr);
		}
	}
	
	public void addLibrary(Profiles profile)
	{
		if(!types.containsKey(profile.getName()) && profile.isActive())
		{
			URI modelURI = null;
			if(profile.getTypeURI() == TypeURI.PATHMAP)
			{
				if(!umlResources.getUriMap().containsKey(URI.createURI(profile.getSource())))
				{
					umlResources.getUriMap().put(URI.createURI(profile.getSource()),
							URI.createURI(profile.getTarget()));
					
				}
				modelURI = URI.createURI(profile.getSource()+profile.getModel());
			} else if(profile.getTypeURI() == TypeURI.PLATFORM) {
				modelURI = URI.createURI(profile.getTarget()+profile.getModel(), true);
			} else {
				modelURI = URI.createURI(profile.getTarget(), true);
			}
			PackageImport pi = umlResources.getModelLibraryImportFromURI(modelURI);
			this.model.getPackageImports().add(pi);
			Resource rs = umlResources.getResourceSet().getResource(modelURI, true);
			Map<String,Type> profileTypes = new HashMap<String, Type>(10);
			if (rs != null) {
	            for (Iterator<EObject> iter = rs.getAllContents(); iter.hasNext();) {
	                EObject eObject = (EObject)iter.next();
	                if (eObject instanceof Type) {
	                	Type pt = (Type)eObject;
	                    profileTypes.put(pt.getName().toLowerCase(), pt);
	                }
	            }
	        }
			types.put(profile.getName(), profileTypes);
		}
	}
		
	public Stereotype getStereotype(String stereotypeName, String profileName)
	{
		Profile umlStdProfile = _profile.get(profileName);
		if(umlStdProfile != null)
		{
			for(Element element : umlStdProfile.getOwnedElements())
			{
				if(element instanceof Stereotype)
				{
					if(((Stereotype) element).getName().equals(stereotypeName))
						return (Stereotype) element;
				}
			}
		}
		return null;
	}
	
	public Stereotype getStereotype(String stereotypeName)
	{
		Iterator<String> iterator = _profile.keySet().iterator();
		while(iterator.hasNext())
		{
			Stereotype stereotype = getStereotype(stereotypeName, iterator.next());
			if(stereotype != null) return stereotype;
		}
		log.debug("No stereotype found for:"+stereotypeName);
		return null;
	}
	
	public Type getType(String typeName, String libraryName)
	{
		if(types.containsKey(libraryName))
		{
			Map<String,Type> stdTypes = types.get(libraryName); 
			if(typeName != null) {
				if(stdTypes.containsKey(typeName.toLowerCase())) {
					return stdTypes.get(typeName.toLowerCase());
				}
			}
		}
		return null;
	}
	
	public Type getType(String typeName)
	{
		Iterator<String> iterator = types.keySet().iterator();
		while(iterator.hasNext())
		{
			Type type = getType(typeName, iterator.next());
			if(type != null) return type;
		}
		log.debug("No type found for:"+typeName);
		return null;
	}
}
